#include "Game.h"
#include "Background.h"
#include "GameOverScene.h"

using namespace cocos2d;

Game::~Game()
{
	if (bird_pos)
	{
		bird_pos->release();
		bird_pos = NULL;
	}
    	CCLog("Game destroy");
	// cpp don't need to call super dealloc
	// virtual destructor will do this
}

Game::Game()
:bird_pos(CCPointZero)
,currentPlatformY(0)
,currentPlatformTag(0)
,currentMaxPlatformStep(0)
,currentBonusPlatformIndex(0)
,currentBonusType(0)
,platformCount(0)
,gameSuspended(false)
,birdLookingRight(false)
,score(0)
{
    CCLog("Game create");
}

CCScene* Game::scene()
{
	CCScene * scene = NULL;
	do 
	{
	    CCLog("Game scene");
		// 'scene' is an autorelease object
		scene = CCScene::create();
		CC_BREAK_IF(! scene);

		// 'layer' is an autorelease object
		Game *layer = Game::create();
		CC_BREAK_IF(! layer);

		// add layer as a child to scene
		scene->addChild(layer);
	} while (0);

	// return the scene
	return scene;
}

// on "init" you need to initialize your instance
bool Game::init()
{
	bool bRet = false;
	do 
	{
	    CCLog("Game init");
		//////////////////////////////////////////////////////////////////////////
		// super init first
		//////////////////////////////////////////////////////////////////////////

		CC_BREAK_IF(! Background::init());

		gameSuspended = true;
        
		// Place the menu item bottom-right conner.
        CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
        CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

		CCSpriteBatchNode *batchNode = (CCSpriteBatchNode*)(this->getChildByTag(kSpriteManager));
		this->initPlatforms();
		CCSprite *bird = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(608,16,44,32));
		batchNode->addChild(bird, 4, kBird);

		CCSprite *bonus;

		for(int i=0; i<kNumBonuses; i++) 
		{
			bonus = CCSprite::spriteWithTexture(batchNode->getTexture(), CCRectMake(608+i*32,256,25,25));
			batchNode->addChild(bonus, 4, kBonusStartTag+i);
			bonus->setVisible(false);
		}

        CCLabelBMFont *scoreLabel = CCLabelBMFont::create("0", "Fonts/bitmapFont.fnt");
	    this->addChild(scoreLabel, 5, kScoreLabel);
	    scoreLabel->setPosition(ccp(visibleSize.width/2,visibleSize.height-20));

		this->setAccelerometerEnabled(true);


		this->schedule( schedule_selector(Game::step));

		this->setTouchEnabled(false);

		this->startGame();

		bRet = true;
	} while (0);

	return bRet;
}

void Game::initPlatforms() 
{
	CCLog("Game initPlatforms");
	currentPlatformTag = kPlatformsStartTag;
	while(currentPlatformTag < kPlatformsStartTag + kNumPlatforms) {
		this->initPlatform();
		currentPlatformTag++;
	}
	
	this->resetPlatforms();
}

void Game::initPlatform()
{
    CCLog("Game initPlatform");
	CCRect rect;
	switch(rand()%2) 
	{
		case 0: rect = CCRectMake(608,64,102,36); break;
		case 1: rect = CCRectMake(608,128,90,32); break;
	}

	CCSpriteBatchNode *batchNode = (CCSpriteBatchNode*)(this->getChildByTag(kSpriteManager));
	CCSprite *platform = CCSprite::spriteWithTexture(batchNode->getTexture(), rect);
	batchNode->addChild(platform, 3, currentPlatformTag);
}

void Game::startGame()
{
    CCLog("Game startGame");
	score = 0;
	
	this->resetClouds();
	this->resetPlatforms();
	this->resetBird();
	this->resetBonus();
	
	gameSuspended = false;
}

void Game::resetPlatforms()
{
	CCLog("Game resetPlatforms");
	currentPlatformY = -1;
	currentPlatformTag = kPlatformsStartTag;
	currentMaxPlatformStep = 60.0f;
	currentBonusPlatformIndex = 0;
	currentBonusType = 0;
	platformCount = 0;

	while(currentPlatformTag < kPlatformsStartTag + kNumPlatforms) 
	{
		this->resetPlatform();
		currentPlatformTag++;
	}
}

void Game::resetPlatform()
{
	if(currentPlatformY < 0) {
		currentPlatformY = 30.0f;
	} else {
		currentPlatformY += rand() % (int)(currentMaxPlatformStep - kMinPlatformStep) + kMinPlatformStep;
		if(currentMaxPlatformStep < kMaxPlatformStep) {
			currentMaxPlatformStep += 0.5f;
		}
	}
	
	CCSpriteBatchNode *batchNode = (CCSpriteBatchNode*)(this->getChildByTag(kSpriteManager));
	CCSprite *platform = (CCSprite*)(batchNode->getChildByTag(currentPlatformTag));
	
	if(rand()%2==1) platform->setScaleX(-1.0f);
	
	float x;
	CCSize size = platform->getContentSize();
	CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
	CCLog("Background resetPlatform winSize:%f x %f", winSize.width, winSize.height);
	if(currentPlatformY == 30.0f) {
		x = winSize.width/2;
	} else {
		x = rand() % ((int)winSize.width-(int)size.width) + size.width/2;
	}

	CCLog("resetPlatform++++++++after  x:%f, y:%f, currentCloudTag:%d", x, currentPlatformY, currentPlatformTag);
	
	platform->setPosition( ccp(x,currentPlatformY));
	platformCount++;
	CCLog("resetPlatform++++++++after  platformCount:%d", platformCount);
	
	if(platformCount == currentBonusPlatformIndex) {
		CCSprite *bonus = (CCSprite*)(batchNode->getChildByTag(kBonusStartTag+currentBonusType));
		bonus->setPosition( ccp(x,currentPlatformY+30));
		bonus->setVisible(true);
	}
}

void Game::resetBird()
{

    CCLog("Game resetBird");
	CCSpriteBatchNode *batchNode = (CCSpriteBatchNode*)(this->getChildByTag(kSpriteManager));
	CCSprite *bird = (CCSprite*)(batchNode->getChildByTag(kBird));

	CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();

	bird_pos = bird->getPosition();
	bird_pos.x = winSize.width/2;
	bird_pos.y = 160;
	bird->setPosition(bird_pos);
	
	bird_vel.x = 0;
	bird_vel.y = 0;
	
	bird_acc.x = 0;
	bird_acc.y = -550.0f;
	birdLookingRight = true;
	bird->setScaleX(1.0f);
}

void Game::resetBonus()
{
	CCLog("Game resetBonus");
	CCSpriteBatchNode *batchNode = (CCSpriteBatchNode*)(this->getChildByTag(kSpriteManager));
	CCSprite *bonus = (CCSprite*)(batchNode->getChildByTag(kBonusStartTag+currentBonusType));
	bonus->setVisible(false);
	currentBonusPlatformIndex += rand() % (kMaxBonusStep - kMinBonusStep) + kMinBonusStep;
	if(score < 10000) {
		currentBonusType = 0;
	} else if(score < 50000) {
		currentBonusType = rand() % 2;
	} else if(score < 100000) {
		currentBonusType = rand() % 3;
	} else {
		currentBonusType = rand() % 2 + 2;
	}
}

void Game::step(float dt)
{
    Background::step(dt);
    if(gameSuspended) return;

    CCSpriteBatchNode *batchNode = (CCSpriteBatchNode*)(this->getChildByTag(kSpriteManager));
	CCSprite *bird = (CCSprite*)(batchNode->getChildByTag(kBird));

	bird_pos.x += bird_vel.x * dt;

	if(bird_vel.x < -30.0f && birdLookingRight) {
		birdLookingRight = false;
		bird->setScaleX(-1.0f);
	} else if (bird_vel.x > 30.0f && !birdLookingRight) {
		birdLookingRight = true;
		bird->setScaleX(1.0f);
	}

	CCSize bird_size = bird->getContentSize();
	CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
	float max_x = winSize.width-bird_size.width/2;
	float min_x = bird_size.width/2;
	
	if(bird_pos.x>max_x) bird_pos.x = max_x;
	if(bird_pos.x<min_x) bird_pos.x = min_x;
	
	bird_vel.y += bird_acc.y * dt;
	bird_pos.y += bird_vel.y * dt;

	CCSprite *bonus = (CCSprite*)(batchNode->getChildByTag(kBonusStartTag+currentBonusType));
	if(bonus->isVisible()) {
		CCPoint bonus_pos = bonus->getPosition();
		float range = 20.0f;
		if(bird_pos.x > bonus_pos.x - range &&
		   bird_pos.x < bonus_pos.x + range &&
		   bird_pos.y > bonus_pos.y - range &&
		   bird_pos.y < bonus_pos.y + range ) {
			switch(currentBonusType) {
				case kBonus5:   score += 5000;   break;
				case kBonus10:  score += 10000;  break;
				case kBonus50:  score += 50000;  break;
				case kBonus100: score += 100000; break;
			}
			//string *scoreStr = [NSString stringWithFormat:@"%d",score];
			char scoreStr[10] = {0};
            sprintf(scoreStr, "%10d", score);
			CCLabelBMFont *scoreLabel = (CCLabelBMFont*)(this->getChildByTag(kScoreLabel));
			scoreLabel->setString(scoreStr);
			//[scoreLabel setString:scoreStr];
			//id a1 = [CCScaleTo actionWithDuration:0.2f scaleX:1.5f scaleY:0.8f];
			//id a2 = [CCScaleTo actionWithDuration:0.2f scaleX:1.0f scaleY:1.0f];
			//id a3 = [CCSequence actions:a1,a2,a1,a2,a1,a2,nil];
			//[scoreLabel runAction:a3];
			this->resetBonus();
		}
	}

	int t;
	
	CCLog("Game step bird_pos = %f x %f", bird_pos.x, bird_pos.y);
	CCLog("Game step bird_vel = %f x %f", bird_vel.x, bird_vel.y);
	CCLog("Game step bird_acc = %f x %f", bird_acc.x, bird_acc.y);
	if(bird_vel.y < 0) {
		
		t = kPlatformsStartTag;
		for(t; t < kPlatformsStartTag + kNumPlatforms; t++) {
			CCSprite *platform = (CCSprite*)(batchNode->getChildByTag(t));

			CCSize platform_size = platform->getContentSize();
			CCPoint platform_pos = platform->getPosition();
			
			max_x = platform_pos.x - platform_size.width/2 - 10;
			min_x = platform_pos.x + platform_size.width/2 + 10;
			float min_y = platform_pos.y + (platform_size.height+bird_size.height)/2 - kPlatformTopPadding;

			
			if(bird_pos.x > max_x &&
			   bird_pos.x < min_x &&
			   bird_pos.y > platform_pos.y &&
			   bird_pos.y < min_y) {

			    CCLog("Game step bird_pos = %f x %f,max_x = %f,platform_pos.y = %f,min_y = %f", bird_pos.x, bird_pos.y,
			        max_x, min_x, platform_pos.y, min_y);
				this->jump();
			}
		}
		
		if(bird_pos.y < -bird_size.height/2) {
			CCLog("Game step bird_pos.y = %f ,bird_size.height/2 = %f", bird_pos.y, -bird_size.height/2);
			CCLog("Game over");
			GameOverScene *gameOverScene = GameOverScene::create();
		    gameOverScene->getLayer()->getLabel()->setString("You Lose :[");
		    CCDirector::sharedDirector()->replaceScene(gameOverScene);
		}
		
	} 
	else if(bird_pos.y > winSize.height/2) {
		
		float delta = bird_pos.y - winSize.height/2;
		bird_pos.y = winSize.height/2;

		currentPlatformY -= delta;
		
		t = kCloudsStartTag;
		for(t; t < kCloudsStartTag + kNumClouds; t++) {
			CCSprite *cloud = (CCSprite*)(batchNode->getChildByTag(t));
			CCPoint pos = cloud->getPosition();
			pos.y -= delta * cloud->getScaleY() * 0.8f;
			if(pos.y < -cloud->getContentSize().height/2) {
				currentCloudTag = t;
				this->resetCloud();
			} else {
				cloud->setPosition(pos);
			}
		}
		
		t = kPlatformsStartTag;
		for(t; t < kPlatformsStartTag + kNumPlatforms; t++) {
			CCSprite *platform = (CCSprite*)(batchNode->getChildByTag(t));
			CCPoint pos = platform->getPosition();
			pos = ccp(pos.x,pos.y-delta);
			if(pos.y < -platform->getContentSize().height/2) {
				currentPlatformTag = t;
				this->resetPlatform();
			} else {
				platform->setPosition(pos);
			}
		}
		
		if(bonus->isVisible()) {
			CCPoint pos = bonus->getPosition();
			pos.y -= delta;
			if(pos.y < -bonus->getContentSize().height/2) {
				this->resetBonus();
			} else {
				bonus->setPosition(pos);
			}
		}
		
		score += (int)delta;
		
		char scoreStr[10] = {0};
        sprintf(scoreStr, "%10d", score);
	    CCLabelBMFont *scoreLabel = (CCLabelBMFont*)(this->getChildByTag(kScoreLabel));
		scoreLabel->setString(scoreStr);

	}
	
	bird->setPosition(bird_pos);
}

void Game::jump(){
    
    bird_vel.y = 350.0f + fabsf(bird_vel.x);
    CCLog("Game jump  bird_vel.y = %f", bird_vel.y);
}

void Game::didAccelerate(CCAcceleration* pAccelerationValue){

    if(gameSuspended) return;
	float accel_filter = 0.1f;
	bird_vel.x = bird_vel.x * accel_filter + pAccelerationValue->x * (1.0f - accel_filter) * 500.0f;
    CCLog("Game didAccelerate  bird_vel.x = %f", bird_vel.x);
}


void Game::registerWithTouchDispatcher()
{
	// CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,0,true);
    CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0);
}
